# !/usr/bin/env python
# -*- coding: utf-8 -*-

"""
<dependency>
    <groupId>org.jpmml</groupId>
    <artifactId>pmml-evaluator</artifactId>
    <version>1.5.8</version>
</dependency>
<dependency>
    <groupId>org.jpmml</groupId>
    <artifactId>pmml-evaluator-extension</artifactId>
    <version>1.5.8</version>
</dependency>
"""

"""
package com.test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.*;
import org.jpmml.model.PMMLUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.math.BigDecimal;
import java.util.*;

public class PmmlTest {

    public static void main(String[] args) throws Exception {
        boolean flag = true;
        // Building a model evaluator from a PMML file
        String modelPath = "D:\\code\\learn\\python-learn\\spark-learn\\out\\house_price.pmml";
        System.out.println(modelPath);
        Evaluator evaluator = new LoadingModelEvaluatorBuilder().load(new File(modelPath)).build();

        // Performing the self-check
        evaluator.verify();

        // Printing input (x1, x2, .., xn) fields
        List<? extends InputField> inputFields = evaluator.getInputFields();
        System.out.println("Input fields: ");
        for (InputField inputField : inputFields) {
            System.out.println(inputField);
        }

        // Printing primary result (y) field(s)
        List<? extends TargetField> targetFields = evaluator.getTargetFields();
        System.out.println("Target field(s): " + targetFields);

        // Printing secondary result (eg. probability(y), decision(y)) fields
        List<? extends OutputField> outputFields = evaluator.getOutputFields();
        System.out.println("Output fields: ");
        for (OutputField outputField : outputFields) {
            System.out.println(outputField);
        }

        List<Map<String, Object>> inputList = new ArrayList<>();
        String json = "{'Id': 1, 'MSSubClass': 60, 'MSZoning': 'RL', 'LotFrontage': '65', 'LotArea': 8450, 'Street': 'Pave', 'Alley': 'NA', 'LotShape': 'Reg', 'LandContour': 'Lvl', 'Utilities': 'AllPub', 'LotConfig': 'Inside', 'LandSlope': 'Gtl', 'Neighborhood': 'CollgCr', 'Condition1': 'Norm', 'Condition2': 'Norm', 'BldgType': '1Fam', 'HouseStyle': '2Story', 'OverallQual': 7, 'OverallCond': 5, 'YearBuilt': 2003, 'YearRemodAdd': 2003, 'RoofStyle': 'Gable', 'RoofMatl': 'CompShg', 'Exterior1st': 'VinylSd', 'Exterior2nd': 'VinylSd', 'MasVnrType': 'BrkFace', 'MasVnrArea': '196', 'ExterQual': 'Gd', 'ExterCond': 'TA', 'Foundation': 'PConc', 'BsmtQual': 'Gd', 'BsmtCond': 'TA', 'BsmtExposure': 'No', 'BsmtFinType1': 'GLQ', 'BsmtFinSF1': 706, 'BsmtFinType2': 'Unf', 'BsmtFinSF2': 0, 'BsmtUnfSF': 150, 'TotalBsmtSF': 856, 'Heating': 'GasA', 'HeatingQC': 'Ex', 'CentralAir': 'Y', 'Electrical': 'SBrkr', '1stFlrSF': 856, '2ndFlrSF': 854, 'LowQualFinSF': 0, 'GrLivArea': 1710, 'BsmtFullBath': 1, 'BsmtHalfBath': 0, 'FullBath': 2, 'HalfBath': 1, 'BedroomAbvGr': 3, 'KitchenAbvGr': 1, 'KitchenQual': 'Gd', 'TotRmsAbvGrd': 8, 'Functional': 'Typ', 'Fireplaces': 0, 'FireplaceQu': 'NA', 'GarageType': 'Attchd', 'GarageYrBlt': '2003', 'GarageFinish': 'RFn', 'GarageCars': 2, 'GarageArea': 548, 'GarageQual': 'TA', 'GarageCond': 'TA', 'PavedDrive': 'Y', 'WoodDeckSF': 0, 'OpenPorchSF': 61, 'EnclosedPorch': 0, '3SsnPorch': 0, 'ScreenPorch': 0, 'PoolArea': 0, 'PoolQC': 'NA', 'Fence': 'NA', 'MiscFeature': 'NA', 'MiscVal': 0, 'MoSold': 2, 'YrSold': 2008, 'SaleType': 'WD', 'SaleCondition': 'Normal', 'SalePrice': 208500, 'LotShape2': 0}";
        inputList.add(JSON.parseObject(json));
        int count = 0;
        for(Map<String, Object> inputRecord: inputList){
            Map<FieldName, FieldValue> arguments = new LinkedHashMap<>();
            // Mapping the record field-by-field from data source schema to PMML schema
            for (InputField inputField : inputFields) {
                FieldName inputName = inputField.getName();
                String alias = inputName.getValue();
                String name = alias;
                String action = null;
                if(name == null){
                    String[] nameArr = alias.split("_");
                    if(nameArr.length != 2){
                        System.out.println("缺少参数:" + alias);
                        return;
                    }
                    name = colMap.get(nameArr[0]);
                    action = nameArr[1];
                }
                Object rawValue = inputRecord.get(name);
                if(rawValue == null){
                    System.out.println("值不能为空:" + alias);
                }
                System.out.println("alias:" + alias + ",rawValue:" + rawValue);
                if("sqrt".equals(action)){
                    rawValue = Math.sqrt(toDouble(rawValue));
                }else if("log".equals(action)){
                    rawValue = Math.log(toDouble(rawValue));
                }else if("abs".equals(action)){
                    rawValue = Math.abs(toDouble(rawValue));
                }else if("exp".equals(action)){
                    rawValue = Math.exp(toDouble(rawValue));
                }
                FieldValue inputValue = inputField.prepare(rawValue);
                arguments.put(inputName, inputValue);
            }
            // Evaluating the model with known-good arguments
            System.out.println("arguments" + JSON.toJSONString(arguments));
            Map<FieldName, ?> results = evaluator.evaluate(arguments);
            System.out.println(results);

            // Decoupling results from the JPMML-Evaluator runtime environment
            Map<String, ?> resultRecord = EvaluatorUtil.decodeAll(results);
            System.out.println(resultRecord);


            count++;
            if(count == 1){
                return;
            }
        }

    }

    public static double toDouble(Object obj){
        if(obj instanceof BigDecimal){
            return ((BigDecimal) obj).doubleValue();
        }else{
            return Double.parseDouble(obj.toString());
        }
    }

}

"""